package net.esj.basic.plugins.spring.support;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.springframework.context.annotation.Scope;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.stereotype.Component;

import net.esj.basic.core.engine.resource.ApplicationResourceBundler;
import net.esj.basic.core.engine.resource.ResourceBundler;

//@Component
//@Scope("prototype")
//FIXME 
public class ApplicationResourceBundleMessageSource extends AbstractMessageSource {

	private String defaultMessages;
	
	private String userMessages;
	
	private Locale defaultLocale;
	
	private ResourceBundler defaultResourceBundler;

	private ResourceBundler userResourceBundler;
	
	private final Map cachedBundleMessageFormats = new HashMap();
	
	public ApplicationResourceBundleMessageSource(String defaultMessages,
			String userMessages) {
		this(defaultMessages,userMessages,Locale.getDefault());
	}

	public ApplicationResourceBundleMessageSource(String defaultMessages,
			String userMessages, Locale defaultLocale) {
		super();
		this.defaultMessages = defaultMessages;
		this.userMessages = userMessages;
		this.defaultLocale = defaultLocale;
		defaultResourceBundler = new ApplicationResourceBundler(defaultMessages);
		userResourceBundler = new ApplicationResourceBundler(userMessages);
	}

	@Override
	protected MessageFormat resolveCode(String code, Locale locale) {
		MessageFormat messageFormat = null;
		
		ResourceBundle bundle = userResourceBundler.getResourceBundle(locale);
		ResourceBundle	defaultbundle = defaultResourceBundler.getResourceBundle(locale);
		if(defaultbundle!=null){
			messageFormat = getMessageFormat(defaultbundle, code, locale);
		}
		if(bundle!=null){
			MessageFormat messageFormat2 = getMessageFormat(bundle, code, locale);
			if(messageFormat2!=null){
				messageFormat = messageFormat2;
			}
		}
		return messageFormat;
	}
	
	protected MessageFormat getMessageFormat(ResourceBundle bundle, String code, Locale locale)
	throws MissingResourceException {

		synchronized (this.cachedBundleMessageFormats) {
			Map codeMap = (Map) this.cachedBundleMessageFormats.get(bundle);
			Map localeMap = null;
			if (codeMap != null) {
				localeMap = (Map) codeMap.get(code);
				if (localeMap != null) {
					MessageFormat result = (MessageFormat) localeMap.get(locale);
					if (result != null) {
						return result;
					}
				}
			}
		
			String msg = getStringOrNull(bundle, code);
			if (msg != null) {
				if (codeMap == null) {
					codeMap = new HashMap();
					this.cachedBundleMessageFormats.put(bundle, codeMap);
				}
				if (localeMap == null) {
					localeMap = new HashMap();
					codeMap.put(code, localeMap);
				}
				MessageFormat result = createMessageFormat(msg, locale);
				localeMap.put(locale, result);
				return result;
			}
			return null;
		}
}
	
	private String getStringOrNull(ResourceBundle bundle, String key) {
		try {
			return bundle.getString(key);
		}
		catch (MissingResourceException ex) {
			return null;
		}
	}
	
}
